package svc

import (
	"errors"
	"fmt"
	"log"
	"os"
	"server-go/rpc/reward/internal/config"
	"strings"

	"github.com/apache/rocketmq-client-go/v2"
	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/rlog"
	"github.com/jordan-wright/email"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type ServiceContext struct {
	Config    config.Config
	Db        *gorm.DB
	Redis     *redis.Redis
	MyMail    *email.Email
	ConsumerA rocketmq.PushConsumer
}

func NewServiceContext(c config.Config) *ServiceContext {
	// mysql
	// 如果运行环境是wsl2 数据库在window本地，使用一下方式
	endIp := c.Mysql.Host
	if ip, err := getWslIp("/etc/resolv.conf"); err == nil {
		endIp = ip
	}
	dataClient := strings.Replace(c.Mysql.Datasource, "$$", endIp, -1)
	db, err := gorm.Open(mysql.Open(dataClient), &gorm.Config{})
	if err != nil {
		return nil
	}
	// 打印出对应的sql
	db.Logger = logger.Default.LogMode(logger.Info)
	// redis
	newRedis := redis.New(c.Redis.Host, redisConfig(c))

	// email
	em := email.NewEmail()
	em.From = c.MyMail.MailNum

	// 消费者, 设置如果消费失败最多重试3次
	consumerA, err := rocketmq.NewPushConsumer(consumer.WithNameServer(
		[]string{c.Rocketmq.Host}),
		consumer.WithConsumerModel(consumer.Clustering),
		consumer.WithGroupName("reward"),
		consumer.WithRetry(3),
	)
	if err != nil {
		log.Println(c.Rocketmq.TopicA + "消费者初始化失败")
		panic(c.Rocketmq.TopicA + "消费者者初始化失败")
	}
	// rocketmq 日志级别
	rlog.SetLogLevel("warn")

	return &ServiceContext{
		Config:    c,
		Db:        db,
		Redis:     newRedis,
		MyMail:    em,
		ConsumerA: consumerA,
	}
}

func redisConfig(c config.Config) redis.Option {
	return func(r *redis.Redis) {
		r.Type = redis.NodeType
		r.Pass = c.Redis.Pass
	}
}

// 获取wsl2 连接window的ip
func getWslIp(path string) (string, error) {
	data, err := os.ReadFile("/etc/resolv.conf")
	if err != nil {
		fmt.Println("File reading error", err)
		return "", err
	}
	fileStr := strings.Replace(string(data), "\n", "", -1)
	ls := strings.Split(fileStr, " ")
	if len(ls) == 0 {
		return "", errors.New("解析失败")
	}
	return ls[len(ls)-1], nil
}
